<?php
/*
Name: Carbon Paper Profiler
Version: 0.1
Author: Bertrand Scarpa
Description: Increase gradually user votes for any posts following goals defined by writer 
Use a distribution profile (Poisson's law)  
*/

include_once('class-post.php');
include_once(INCLUDEPATH . 'logfile.php');
include_once(INCLUDEPATH . 'class-date.php');

class CProfiler{
	
	const DAY_START_HOUR 				=  9;
	const DAY_END_HOUR					=  0;
	const WEEKDAY_START_HOUR			=  9;
	const WEEKDAY_END_HOUR				= 17;
	const WEEKDAY_SESSION_CADENCE		=  3; 
	
	private static $defaults = array(
		'included_types' 	=> array('buzz'),
		'duration' 			=> 360, 	//hours
		'location' 			=> 63, 		//hours
		'scale' 			=> 25, 		
		'offset' 			=> 0, 		//hours
		'r' 				=> 0, 		//%
		'mode' 				=> 'edit', 
	);
	

	private static $instance = null;
	public 	static $included_types;
	public 	static $duration;				// Duration of push (hours)
	public 	static $location;				// Location of peak distribution (hours)
	public  static $interval;				// Job Execution interval(hours)
	public 	static $dayjob_rule;			// Job Rule
	public 	static $weekdayjob_rule;		// Job Rule
	public  static $r;						// Wished marge for each gain (%) 
	public  static $mode;					// 'debug' or 'edit' 
	public 	static $jobs;

	private function __construct(){
		$args = $this->get_parameters();
		self::$included_types 	= $args['included_types'];
		self::$duration 		= $args['duration'];
		self::$interval			= $args['interval'];
		self::$location 		= $args['location'];
		self::$dayjob_rule		= $args['dayjob_rule'];
		self::$weekdayjob_rule	= $args['weekdayjob_rule'];
		self::$r 				= $args['r'];
		self::$mode 			= $args['mode'];
		$this->set_jobs();
	}
	
	public function get_instance(){
		if(is_null(self::$instance)) {
				self::$instance = new CProfiler();  
		}
 		return 	self::$instance;
	}
	
	
	public function get_parameters(){
		global $wpdb;
		$rParameters = $wpdb->get_var("SELECT option_value from {$wpdb->options} where option_name = 'voteprofiler'");
		$parameters = unserialize($rParameters);
		$parameters = wp_parse_args($parameters, self::$defaults);

		return $parameters;
	}
	
	
	// Excecuted by interval via cronjob :
	public function process(){
		// Test if plugin reaction-button is registered
		$current_plugins = get_option('active_plugins');
		if (in_array('reaction-buttons/reaction_buttons.php', $current_plugins)) {

			if ($this->has_job()){
				// Get posts included in the defined duration
				$posts = $this->get_posts_by_duration();
				if ($posts){
					foreach ($posts as $oPost) {
						
						// For each vote created in the post :
						$votes = $oPost->get_votes(); 
						if ($votes){
							foreach ($votes as $oVote) {
								
								// Update
								$oVote->update();
							}
						}
					}
				}
			}
		}
	}
	
	public function set_jobs(){
		$dNow = new Datetime('now');
		$dStart = date_sub($dNow, "P" . self::$duration . "H")->datetime();
	 	for ($i = 0; $i < (2 * self::$duration) - 1; $i+=self::$interval){

			$job_status = 1;
			$job_date = date_add($dStart,"P{$i}H");

			// Rule : no job during night
			if (self::$dayjob_rule){
			$job_status &= ($job_date->h >= self::DAY_END_HOUR && $job_date->h < self::DAY_START_HOUR) ? 0 : 1;
			}

			// Rule : tiers time during days of week 
			if (self::$weekdayjob_rule){
				$job_status &= ($job_date->w > 0 
					&& $job_date->w < 6 
					&& $job_date->h >= self::WEEKDAY_START_HOUR
					&& $job_date->h <= self::WEEKDAY_END_HOUR
					&& fmod((int)$job_date->h - self::WEEKDAY_START_HOUR,self::WEEKDAY_SESSION_CADENCE) != 0 
				) ? 0 : 1;			
			}

			//echo "$job_date->w $job_date->h  $job_status <br>"; 
			$jobs[$i] = $job_status; 
		}
		self::$jobs  = $jobs;
	}
	
	public function has_job(){
		return ($this->jobs[self::$duration] == 1); 
	}
	
		
	public function get_posts_by_duration(){
		global $wpdb;
		// Get the working set of posts included in the push vote $duration 
		$included_types_clause = (!is_null(self::$included_types) || self::$included_types <> '') ? " AND post_type IN('" . join("','",explode(',',preg_replace('/\s+/','', self::$included_types))) . "') " : "";
		$rPosts = $wpdb->get_results("SELECT ID, post_title, post_type, post_date FROM {$wpdb->posts} WHERE TIME_TO_SEC(TIMEDIFF(Now(),post_date)) / 3600 <=" . self::$duration . " AND post_status = 'publish'" . $included_types_clause);
		foreach ($rPosts as $rPost){
			$oPost = new CPost($rPost->ID);
			$oPost->set_title($rPost->post_title);
			$oPost->set_type($rPost->post_type);
			$oPost->set_date($rPost->post_date);
			$oPost->set_scope($rPost->post_date);
			$oPost->set_session($rPost->post_date);
			$posts[] = $oPost;
		}
		return $posts;
	}
	
	public function get_post_by_id($ID){
		global $wpdb;
		$rPost = $wpdb->get_row("SELECT ID, post_title, post_type, post_date FROM {$wpdb->posts} WHERE ID=" . $ID);
		$oPost = new CPost($rPost->ID);
		$oPost->set_title($rPost->post_title);
		$oPost->set_type($rPost->post_type);
		$oPost->set_date($rPost->post_date);
		$oPost->set_scope($rPost->post_date);
		$oPost->set_session($rPost->post_date);
		return $oPost;
	}
}
?>